\ Menu class. \ Sept 90 mrh item# anomalies fixed :class MENU super{ x-array } int RESID \ Resource ID of this menu var MHNDL \ Handle to menu heap storage :m ID: inline{ get: resID} get: resID ;m :m PUTRESID: inline{ put: resID} put: resID ;m :m HANDLE: inline{ get: mHndl} get: mhndl ;m :m INIT: \ ( xt1 ... xtN N resID -- ) put: resID put: super ;m :m NEW: \ ( addr len -- ) Allocates menu with title. \ Non-resource-based. str255 >r 0 int: resid r> call NewMenu put: Mhndl ;m \ GetNew: and Release: are used if the menu is resource-based. :m GETNEW: 0 int: resid call GetRMenu dup 0= ?error 127 put: mHndl ;m :m RELEASE: get: mHndl call ReleaseResource ;m :m INSERT: \ Inserts the menu in the menu bar. get: Mhndl word0 call InsertMenu ;m :m NORMAL: \ Removes hiliting on ALL menus! word0 call HiliteMenu ;m :m ENABLE: \ Enables a whole menu. get: Mhndl word0 call EnableItem call DrawMenuBar ;m :m DISABLE: \ Greys and disables a whole menu. get: Mhndl word0 call DisableItem call DrawMenuBar ;m \ Methods dealing with individual menu items. We index from zero, as normal \ in Mops. BUT NOTE that this is different from the Toolbox convention \ relating to menu items. :m GETITEM: \ ( item# -- addr len ) Gets string for item# get: mhndl swap 1+ makeint buf255 call GetItem buf255 count ;m :m PUTITEM: { item# addr len -- } \ Replaces menu item string get: mhndl item# 1+ makeint addr len str255 call SetItem ;m :m INSERTITEM: { item# addr len -- } \ Inserts a new item, after item#. get: mhndl addr len str255 item# 1+ makeint call InsMenuItem ;m :m DELETEITEM: \ ( item# -- ) Deletes the item. get: mhndl swap 1+ makeint call DelMenuItem ;m :m ADD: \ ( addr len -- ) Appends a menu item str255 get: Mhndl swap call AppendMenu ;m :m ADDITEM: add: self ;m \ Just for naming consistency :m ADDRES: \ ( type -- ) Adds all resources of a type get: Mhndl swap call AddResMenu ;m :m ENABLEITEM: \ ( item# -- ) Enables a menu item get: Mhndl swap 1+ makeint call EnableItem ;m :m DISABLEITEM: \ ( item# -- ) Greys and disables an item get: Mhndl swap 1+ makeint call DisableItem ;m :m OPENDESK: \ ( item# -- ) Opens the desk accy for item# savePort getitem: self 2drop word0 buf255 call OpenDeskAcc word0 drop restPort ;m :m EXEC: \ ( item# -- ) Executes the code for a menu item. \ Menu handlers will have item# on the stack when they execute, and they \ should leave it there. This way, they can ignore it if they want to, \ which will be the most common situation. \ If the item# is too great for this menu, we actually execute the last \ item rather than give an error. This allows us to save memory \ when a menu may have dozens of identical items such as fonts or DAs, as \ can happen with Font/DA Juggler or Suitcase. But of course we don't \ alter the item# on the stack. dup limit 1- min exec: super drop normal: self ;m :m CHECK: \ ( item# -- ) get: Mhndl swap 1+ makeInt w 256 call CheckItem ;m :m UNCHECK: \ ( item# -- ) get: Mhndl swap 1+ makeInt word0 call CheckItem ;m ;class \ Subclass AppleMenu facilitates standard Apple Menu support, by filling \ the menu with all the DAs at GetNew: time. :class APPLEMENU super{ menu } :m GETNEW: getnew: super 'type DRVR addRes: self ;m ;class \ Subclass EditMenu facilitates standard DA support. The EXEC: method \ first calls SystemEdit so any active DA gets a go at it. :class EDITMENU super{ menu } :m EXEC: { item# -- } word0 item# makeint call SystemEdit i->l IF normal: self ELSE item# exec: super THEN ;m ;class